Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue#1275 #2181

Merged
merged 6 commits into from
Jun 23, 2020
Merged

Fix issue#1275 #2181

merged 6 commits into from
Jun 23, 2020

Conversation

dota17
Copy link
Contributor

@dota17 dota17 commented Jun 10, 2020

Fix issue #1275 : add an overload of function value(key, default_value).


Pull request checklist

Read the Contribution Guidelines for detailed information.

  • Changes are described in the pull request, or an existing issue is referenced.
  • The test suite compiles and runs without error.
  • Code coverage is 100%. Test cases can be added by editing the test suite.
  • The source code is amalgamated; that is, after making changes to the sources in the include/nlohmann directory, run make amalgamate to create the single-header file single_include/nlohmann/json.hpp. The whole process is described here.

@dota17 dota17 requested a review from nlohmann as a code owner June 10, 2020 11:34
@coveralls
Copy link

coveralls commented Jun 10, 2020

Coverage Status

Coverage remained the same at 100.0% when pulling 4a6c68c on dota17:issue#1275 into 27f5a6e on nlohmann:develop.

@FrancoisChabot
Copy link
Contributor

FrancoisChabot commented Jun 12, 2020

Reading through #1275, my impression is that the consensus was that moving out the value from the json object was deemed too surprising for users.

That aside, value() being a either a pure accessor or mutator depending on context sounds like a recipe for disaster.

So in my mind, this PR should either:

  1. Name the new function a different name than an existing function, to reflect the fact that it does something else.
  2. Be an update to the existing function to make it move out the held value (which would not be backwards compatible, so it would be a 4.0.0 change)
  3. Be an update to the existing function that simply expands the range of legal values for the default_value argument.

@dota17
Copy link
Contributor Author

dota17 commented Jun 15, 2020

@FrancoisChabot thank your advices! I think the first point is better, cause the second one will wait until the next major release, that will be a very long time. And the third one, I think it isn't the thing about the range of the default value.
But right now, I haven't got a new function name, I saw someone proposed to name pop_value(),
how do you think?

@FrancoisChabot
Copy link
Contributor

FrancoisChabot commented Jun 15, 2020

Pedantically, I think this PR should ideally be 3), since that's what #1275 is about. 1) is practically a new feature in of itself.

But honestly, I'm personally not a huge fan of 1). I do not like extra API surface for the sake of minor QoL features in general. I can do std::move(json_obj.get_ref<std::string>()), and that's good enough for me. I've got enough cognitive load to deal with as it is.

@nlohmann
Copy link
Owner

I'm against breaking the API, and I am not really convinced that adding a new function is really helpful. This is a very small corner case, and it is possible to implement it via the public API.

@dota17
Copy link
Contributor Author

dota17 commented Jun 16, 2020

Ok, I will not add a new function to break the API, but only focus on 3).
But I am confused with the meaning of expanding the range of the default_value.

@FrancoisChabot
Copy link
Contributor

It's just an awkward way of saying that the function would now accept R-Value references when appropriate.

@dota17
Copy link
Contributor Author

dota17 commented Jun 22, 2020

@nlohmann @FrancoisChabot Are you satisfied with the last changes?

@FrancoisChabot
Copy link
Contributor

This looks fine to me.

Copy link
Owner

@nlohmann nlohmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@nlohmann nlohmann self-assigned this Jun 23, 2020
@nlohmann nlohmann added this to the Release 3.8.1 milestone Jun 23, 2020
@nlohmann nlohmann merged commit 8575fdf into nlohmann:develop Jun 23, 2020
@nlohmann
Copy link
Owner

Thanks!

@nlohmann

This comment has been minimized.

@dota17 dota17 deleted the issue#1275 branch June 23, 2020 07:25
@lethe555
Copy link

lethe555 commented Jul 3, 2020

just break my code

json j{{"x", "test"}};
std::string defval = "default value";
auto val = j.value("x",defval);
auto val2 = j.value("y",defval);

json.hpp:19714:25: warning: returning reference to temporary [-Wreturn-local-addr]
return *it;

@gregmarr
Copy link
Contributor

gregmarr commented Jul 7, 2020

@lethe555 Which line is 19714? Assuming it's the return *it, you haven't shown us what it is.

@lethe555
Copy link

lethe555 commented Jul 8, 2020

@gregmarr

json j{{"x", "test"}};
std::string defval = "default value";
auto val = j.value("x",defval);
auto val2 = j.value("y",defval);

error: no matching function for call to 'nlohmann::basic_json<>::value(const char [2], std::string&)'
auto val = j.value("x", defval);

now default_value seems can't be a lvalue , but use a lvalue as default value is very common case

@nlohmann
Copy link
Owner

nlohmann commented Jul 8, 2020

I can confirm that the code in #2181 (comment) does not compile with the latest develop version. Reason is this PR. I shall revert the changes and add a regression test. Then, we can decide how to properly address #1275.

@nlohmann nlohmann removed this from the Release 3.8.1 milestone Jul 8, 2020
nlohmann added a commit that referenced this pull request Jul 8, 2020
@nlohmann
Copy link
Owner

nlohmann commented Jul 8, 2020

Done.

@gregmarr
Copy link
Contributor

gregmarr commented Jul 8, 2020

I think you might be able to do this same basic PR but using std::forward instead of std::move.

nlohmann added a commit that referenced this pull request Jul 9, 2020
@nlohmann
Copy link
Owner

nlohmann commented Jul 9, 2020

I can't get it to run:

../test/src/unit-regression.cpp:1954:22: error: no matching member function for call to 'value'
        auto val = j.value("x", defval);
                   ~~^~~~~
../include/nlohmann/json.hpp:3810:14: note: candidate function not viable: no known conversion from 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to 'const char *' for 2nd argument
    string_t value(const typename object_t::key_type& key, const char* default_value) const
             ^
../include/nlohmann/json.hpp:3884:14: note: candidate function not viable: no known conversion from 'const char [2]' to 'const nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >::json_pointer' (aka 'const json_pointer<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > > >') for 1st argument
    string_t value(const json_pointer& ptr, const char* default_value) const
             ^
../include/nlohmann/json.hpp:3788:15: note: candidate template ignored: requirement 'std::is_convertible<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > &>::value' was not satisfied [with ValueType = std::__1::basic_string<char> &]
    ValueType value(const typename object_t::key_type& key, ValueType&& default_value) const
              ^
../include/nlohmann/json.hpp:3860:15: note: candidate template ignored: requirement 'std::is_convertible<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::allocator, adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > &>::value' was not satisfied [with ValueType = std::__1::basic_string<char> &]
    ValueType value(const json_pointer& ptr, ValueType&& default_value) const

@dota17
Copy link
Contributor Author

dota17 commented Jul 9, 2020

@nlohmann
Please see dota17#18, I made a new PR in my fork repo for this issue.
And from CI log, the test SECTION("PR #2181 - regression bug with lvalue") had no error for new PR.
I just added back the original method and then there would be two methods:

ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const //  added back
...
ValueType value(const typename object_t::key_type& key, ValueType && default_value) const

If you think it works, I would push it to the official repo.

@nlohmann
Copy link
Owner

nlohmann commented Jul 9, 2020

That would be great.

@dota17 dota17 mentioned this pull request Jul 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggestion to improve value() accessors with respect to move semantics
6 participants